#!/usr/bin/python2.7
import sys
import getopt

from PyQt4 import QtGui, QtCore
from libVirgil.converter import converter
from libVirgil import ddithreecodecategories as ddi31CC
from libVirgil.ui.csv2DdiConvertorWindow_auto import Ui_csv2DdiConvertorWindow as Ui_csv2ddi

VERSION = "0.0.3"
REVISION = "$Revision: 39 $".replace("$","") #SVN Attribute that gets updated on each check-in (we remove the $ $'s to make it readable

class converter_ui(QtGui.QMainWindow):
    def __init__(self, parent=None,standalone=False, ddi=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_csv2ddi()
        self.defaultLanguage  = "en-au"  #flag for the user preferred langauge when displaying DDI
        self.ui.setupUi(self)
        self.standalone = standalone
        if not standalone:
            #We are running this as a wizard in some other software, hide the silly blame button
            self.ui.BlameButton.setVisible(False)
        else:
            self.ui.BlameButton.clicked.connect(self.vanityBox)
        self.ui.CancelButton.clicked.connect(self.close)
        self.parent = parent
        # here we connect signals with our slots

        #connect Buttons to methods
        self.ui.processCSV.clicked.connect(self.convert)
        self.ui.openFile.clicked.connect(self.openFile)
        self.ui.hasHeader.toggled.connect(self.setTableHeaders)

        self.ui.csvPreview.clear()
        self.setTableHeaders()

    def vanityBox(self):
        vanityText = """<html>
<head>
<meta name="qrichtext" content="1" />
</head>
<body>
<p>
<h1>Virgil c2d - CSV -> DDI Converter v{version}</h1>
</p>
<p>
{revision} Released under GPLv3 Licence<br>
Details available at: <a href="http://code.google.com/p/virgil-ui/">http://code.google.com/p/virgil-ui/<a>
</p>
<p>
Primary Developer: <a href="http:/about.me/legostormtroopr">Samuel Spencer</a>
</p>
</body>
</html>
""".format(version=VERSION,revision=REVISION)
        QtGui.QMessageBox.about(self,"About Virgil UI", vanityText )
    #returns True if the file was successfully save, false otherwise

    def openFile(self):
    #trigger save question here
        file = QtGui.QFileDialog.getOpenFileName(self, 'Open CSV File', '.')
        self.filename = file
        self.showPreview()

    def showPreview(self):
        import csv

        self.ui.labelFilename.setText(self.filename + " ")
        self.ui.labelFilename.setToolTip(self.filename)

        self.ui.csvPreview.clear()
        maxlen = 0
        i = 0
        num = 15
        self.ui.csvPreview.setRowCount(num)

        with open(self.filename, 'rb') as f: 
            csvfile = csv.reader(f, delimiter=',')

            for row in csvfile:
                if i >= num:
                    break
                maxlen = max(maxlen,len(row))
                for j in range(0,len(row)):
                    if j > self.ui.csvPreview.columnCount():
                        self.ui.csvPreview.setColumnCount(j)
                    self.ui.csvPreview.setItem(i,j,QtGui.QTableWidgetItem(row[j]))
                i = i + 1
        self.setTableHeaders()

    def setTableHeaders(self):
        headers = ["Header"]+range(1,self.ui.csvPreview.rowCount()+1)
        hasHeader = int(not self.ui.hasHeader.isChecked())
        for i in range(0,self.ui.csvPreview.rowCount()):
            self.ui.csvPreview.setVerticalHeaderItem(i,QtGui.QTableWidgetItem(str(headers[i+hasHeader])))

    # Thanks to http://stackoverflow.com/questions/845058/how-to-get-line-count-cheaply-in-python 
    def file_len(self):
        with open(self.filename) as f:
            for i, l in enumerate(f):
                pass
        return i + 1

    def convert(self):
         
        # process options
        sep             = ","
        hasHeader       = True
        outtype         = converter.outputTypes.DDI31
        codetype        = converter.codeTypes.Referential
        categorytype    = converter.categoryTypes.PrefixEmbedded
        defaultLanguage = 'en'
        ddiID           = str(self.ui.ddiIDPrefix.text())


        if   self.ui.hasHeader.isChecked():
            hasHeader = True
        else:
            hasHeader = False

        numfiles = self.file_len()*2        # Times to as we do 2 loops through, one to mine the info, and a second to add. This makes it easier to revert if there is a failure
        dialog = QtGui.QProgressDialog("Converting...","Cancel",0,numfiles,self)    
        dialog.forceShow() 

        # Check codes
        if   self.ui.rbCodeHierarchy_Referential.isChecked():
            codetype = converter.codeTypes.Referential
        elif self.ui.rbCodeHierarchy_ReverseReferential.isChecked():
            codetype = converter.codeTypes.ReverseReferential
        elif self.ui.rbCodeHierarchy_SemiStructured.isChecked():
            codetype = converter.codeTypes.SemiStructured
        elif self.ui.rbCodeHierarchy_AlignedSemiStructured.isChecked():
            codetype = converter.codeTypes.AlignedSemiStructured
        
        # Check categories
        if   self.ui.rbCategoryLanguage_PrefixEmbedded.isChecked():
            categorytype = converter.categoryTypes.PrefixEmbedded
        elif self.ui.rbCategoryLanguage_PreDefinedColumn.isChecked():
            categorytype = converter.categoryTypes.PreDefinedColumn
        elif self.ui.rbCategoryLanguage_Monolingual.isChecked():
            categorytype = converter.categoryTypes.Monolingual
            defaultLanguage = str(self.ui.CategoryLanguage_MonolingualLanguage.text())

        con = converter.converter(file=self.filename, header=hasHeader, sep=sep, defaultLanguage=defaultLanguage,
                             codetype=codetype, categorytype=categorytype, output=outtype)

        categorySchemeID = "%s__cat"%ddiID
        codeSchemeID = "%s__code"%ddiID
        # check which output format we need
        if self.parent is None:
            output = None
            if con.outputtype == converter.outputTypes.DDI31:
                output = ddi31CC.ddi_CC_wrapper(id=ddiID)
        else:
            output = self.parent.ddi

        code_id_prepend = codeSchemeID
        category_id_prepend = categorySchemeID
        try:
            classns = []
            for classn in con.convert():
                if dialog.wasCanceled():
                    break # NOT A GOTO    
                print classn['labels'].get('fr', 'none')
                classn['code_id']     = "%s__%s"%(code_id_prepend,classn['code'])
                classn['category_id'] = "%s__%s"%(category_id_prepend,classn['code'])
                if classn['parent'] is not None:
                    classn['parent']  = "%s__%s"%(code_id_prepend,classn['parent'])
                else:
                    classn['parent']  = "%s"%(codeSchemeID)
                    
                classns.append((classn,codeSchemeID,categorySchemeID))
                dialog.setValue(dialog.value() + 1) 
            
            output.newCategoryScheme(categorySchemeID)
            output.newCodeScheme(codeSchemeID)
            # We add the classifications in a second step as it makes clean up easier if there is an error in the imported CSV.
            for classn, codeSchemeID, categorySchemeID in classns:
                print classn
                output.newCodeCategory(classn,codeSchemeID,categorySchemeID)
                dialog.setValue(dialog.value() + 1) 
                
            # If we finish the loop flawlessly but the dialog hasn't finished, lets just force it to 'complete' 
            if dialog.value() < dialog.maximum():
                dialog.setValue(dialog.maximum())
        except:
            lineno = dialog.value()
            dialog.cancel()
            title = "Error"
            message = "An error occurred reading line %s in the file '%s':\n%s"%(lineno,self.filename,sys.exc_info()[0])
            err = QtGui.QMessageBox.critical(self,title,message,QtGui.QMessageBox.AcceptRole,QtGui.QMessageBox.AcceptRole)
         

        if self.standalone:
            if not dialog.wasCanceled(): 
                filename = QtGui.QFileDialog.getSaveFileName(self, 'Save File As', '.')
                if filename != "":
                    with open(filename, 'w') as f:
                        output.saveToFile(f)
            else:
                title = "Process canceled"
                message = "Conversion process canceled.\nUnable to save."
                err = QtGui.QMessageBox.information(self,title,message,QtGui.QMessageBox.AcceptRole,QtGui.QMessageBox.AcceptRole)
        else:
            self.parent.updateModelAsDDITree(ddi=self.parent.ddi)
            self.close()
             

#Thanks Guido
class Usage(Exception):
    def __init__(self, msg):
            self.msg = msg

def main(argv=None):
    if argv is None:
        argv = sys.argv
    try:
        try:
            opts, args = getopt.getopt(argv[1:], "hs:", ["help","standalone="])
        except getopt.error, msg:
             raise Usage(msg)

        sa = True
        for o,a in opts:
            if o in ('-s','--standalone'):
                sa = not (a=="False" or a=="0")

        app = QtGui.QApplication(sys.argv)
        w = converter_ui(standalone=sa)
        w.show()

        sys.exit(app.exec_())

    except Usage, err:
        print >>sys.stderr, err.msg
        print >>sys.stderr, "for help use --help"
        return 2

if __name__ == "__main__":
    sys.exit(main())

